import { Meta } from "@storybook/addon-docs";

<Meta title="Documentation/Virtual Scrolling" />

# Virtual Scrolling

Virtual scrolling is a technique that improves the rendering performance of very large lists by only
rendering whatever is currently visible within the viewport. We build on top of
[Angular CDK's `ScrollingModule`](https://material.angular.dev/cdk/scrolling/overview).

## Scrolling the entire layout

Often, a design calls for the scroll container to envelop the entire page. To support this,
AngularCDK provides a `scrollWindow` directive that sets the window to be virtual scroll viewport.
We export a similar directive, `bitScrollLayout`, that integrates with `bit-layout` and `popup-page`
and should be used instead of `scrollWindow`.

```html
<!-- Descendant of bit-layout or popup-page -->
<cdk-virtual-scroll-viewport bitScrollLayout>
  <!-- virtual scroll implementation here -->
</cdk-virtual-scroll-viewport>
```

### Known footgun

Due to the initialization order of Angular components and their templates, `bitScrollLayout` will
error if it is used _in the same template_ as the layout component:

With `bit-layout`:

```html
<!-- Will cause `bitScrollLayout` to error -->
<bit-layout>
  <cdk-virtual-scroll-viewport bitScrollLayout>
    <!-- virtual scroll implementation here -->
  </cdk-virtual-scroll-viewport>
</bit-layout>
```

With `popup-page`:

```html
<!-- Will cause `bitScrollLayout` to error -->
<popup-page>
  <cdk-virtual-scroll-viewport bitScrollLayout>
    <!-- virtual scroll implementation here -->
  </cdk-virtual-scroll-viewport>
</popup-page>
```

In this particular composition, the child content gets constructed before the template of
`bit-layout` (or `popup-page`) and thus has no scroll container to reference. Workarounds include:

1. Wrap the child in another component. (This tends to happen by default when the layout is
   integrated with a `router-outlet`.)

With `bit-layout`:

```html
<bit-layout>
  <component-that-contains-bitScrollLayout></component-that-contains-bitScrollLayout>
</bit-layout>
```

With `popup-page`:

```html
<popup-page>
  <component-that-contains-bitScrollLayout></component-that-contains-bitScrollLayout>
</popup-page>
```

2. Use a `defer` block.

With `bit-layout`:

```html
<bit-layout>
  @defer (on immediate) {
    <cdk-virtual-scroll-viewport bitScrollLayout>
      <!-- virtual scroll implementation here -->
    </div>
  }
</bit-layout>
```

With `popup-page`:

```html
<popup-page>
  @defer (on immediate) {
    <cdk-virtual-scroll-viewport bitScrollLayout>
      <!-- virtual scroll implementation here -->
    </div>
  }
</popup-page>
```
